package com.purdue.edu.psychotron.client;


import com.purdue.edu.psychotron.client.service.UserService;
import com.purdue.edu.psychotron.client.service.UserServiceAsync;
import com.purdue.edu.psychotron.shared.FieldVerifier;
import com.purdue.edu.psychotron.shared.SideBar;
import com.purdue.edu.psychotron.shared.UUID;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.PasswordTextBox;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class Psychic_transmitter implements EntryPoint {
	/**
	 * The message displayed to the user when the server cannot be reached or
	 * returns an error.
	 */
	private static final String SERVER_ERROR = "An error occurred while "
		+ "attempting to contact the server. Please check your network "
		+ "connection and try again.";

	/**
	 * Create a remote service proxy to talk to the server-side Greeting service.
	 */
	private final GreetingServiceAsync greetingService = GWT.create(GreetingService.class);
	private final UserServiceAsync userService = GWT.create(UserService.class);
	/**
	 * This is the entry point method.
	 */
	public void onModuleLoad() 
	{
		final Label secretUserId = new Label(); 
		secretUserId.setVisible(false);			// This will be used to locally store the user's UUID as the only way to work with server
		RootPanel.get("divLogin").setVisible(true);
		/*----------------------------divLogin-------------------------------------*/
		final Button loginButton = new Button("Log In");
		final Button signUpButton = new Button("Sign Up");
		final TextBox loginField = new TextBox();
		loginField.setText("Enter Username");
		final PasswordTextBox passwordField = new PasswordTextBox();
		passwordField.setText("Enter Password");
		final Label errorLabel = new Label();

		// We can add style names to widgets
		//	loginButton.addStyleName("loginButton");
		//	signUpButton.addStyleName("signUpButton");
		// Add the loginField and loginButton to the RootPanel
		// Use RootPanel.get() to get the entire body element
		RootPanel.get("divLogin").add(loginField);
		RootPanel.get("divLogin").add(passwordField);
		RootPanel.get("divLogin").add(loginButton);
		RootPanel.get("divLogin").add(signUpButton);
		RootPanel.get("divLogin").add(errorLabel);

		// Focus the cursor on the name field when the app loads
		loginField.setFocus(true);
		loginField.selectAll();


		/*-----------------------------------------------------------------------*/

		/*-------------------------------Shared among Divs-----------------------------------*/

		// Create the popup dialog box
		final DialogBox clientServerDialogBox = new DialogBox();
		clientServerDialogBox.setText("Remote Procedure Call");
		clientServerDialogBox.setAnimationEnabled(true);

		final Button closeButton = new Button("Close");
		// We can set the id of a widget by accessing its Element
		closeButton.getElement().setId("closeButton");


		final Label textToServerLabel = new Label();
		final HTML serverResponseLabel = new HTML();
		VerticalPanel dialogVPanel = new VerticalPanel();
		//		dialogVPanel.addStyleName("dialogVPanel");
		dialogVPanel.add(new HTML("<b>Sending name to the server:</b>"));
		dialogVPanel.add(textToServerLabel);
		dialogVPanel.add(new HTML("<br><b>Server replies:</b>"));
		dialogVPanel.add(serverResponseLabel);
		dialogVPanel.setHorizontalAlignment(VerticalPanel.ALIGN_RIGHT);
		dialogVPanel.add(closeButton);
		clientServerDialogBox.setWidget(dialogVPanel);

		// Add a handler to close the DialogBox
		closeButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				clientServerDialogBox.hide();
				loginButton.setEnabled(true);
				loginButton.setFocus(true);
			}
		});
		/*-----------------------------------------------------------------------*/

		/*-------------------------------divRegistration-----------------------------------*/
		final TextBox newLoginField = new TextBox();
		newLoginField.setText("New Login");
		final PasswordTextBox newPasswordField = new PasswordTextBox();
		newPasswordField.setText("Password");
		final TextBox fisrtNameField = new TextBox();
		fisrtNameField.setText("First Name");
		final TextBox lastNameField = new TextBox();
		lastNameField.setText("Last Name");
		final Button registerButton = new Button("Register");
		final Button cancelButton = new Button("Cancel");
		RootPanel.get("divRegistration").add(fisrtNameField);
		RootPanel.get("divRegistration").add(lastNameField);
		RootPanel.get("divRegistration").add(newLoginField);
		RootPanel.get("divRegistration").add(newPasswordField);
		RootPanel.get("divRegistration").add(registerButton);
		RootPanel.get("divRegistration").add(cancelButton);
		/*-----------------------------------------------------------------------*/

		/*-------------------------------divLobby-----------------------------------*/
		SideBar sideBar = new SideBar();
		final Button cloudMsgrButton = new Button("Cloud Messenger");
		final Button cloudStorageButton= new Button("Cloud Storage");
		sideBar.add(cloudMsgrButton);
		sideBar.add(cloudStorageButton);
		RootPanel.get("divLobby").add(sideBar);

		cloudMsgrButton.addClickHandler(new ClickHandler(){

			@Override
			public void onClick(ClickEvent event) {
				//		Window.alert("Entering Cloud Messenger.");
				RootPanel.get("divCloudMessenger").clear();   
				RootPanel.get("divLobby").setVisible(false);
				RootPanel.get("divCloudMessenger").setVisible(true);		
				RootPanel.get("divCloudMessenger").add(new CloudMessenger(secretUserId.getText()));
				userService.initializeCloudMessengerForUserId(secretUserId.getText(), new AsyncCallback<Void>(){

					@Override
					public void onFailure(Throwable caught) {
						Window.alert("initializeCloudMessengerForUserId - Failure");

					}

					@Override
					public void onSuccess(Void result) {
						// TODO Auto-generated method stub

					}

				});
			}

		});
		/*-----------------------------------------------------------------------*/

		// Create a handler for the loginButton and loginField
		class MyHandler implements ClickHandler, KeyUpHandler 
		{
			/**
			 * Fired when the user clicks on the loginButton.
			 */
			public void onClick(ClickEvent event) {
				sendNameToServer();
			}

			/**
			 * Fired when the user types in the loginField.
			 */
			public void onKeyUp(KeyUpEvent event) {
				if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
					sendNameToServer();
				}
			}

			/**
			 * Send the name from the loginField to the server and wait for a response.
			 */
			private void sendNameToServer() 
			{
				// First, we validate the input.
				errorLabel.setText("");
				String textToServer = loginField.getText();
				if (!FieldVerifier.isValidName(textToServer)) {
					errorLabel.setText("Please enter at least four characters");
					return;
				}

				// Then, we send the input to the server.
				loginButton.setEnabled(false);
				textToServerLabel.setText(textToServer);
				serverResponseLabel.setText("");
				greetingService.greetServer(textToServer, 
						new AsyncCallback<String>() 
						{
					public void onFailure(Throwable caught) {
						// Show the RPC error message to the user
						clientServerDialogBox.setText("Remote Procedure Call - Failure");
						serverResponseLabel.addStyleName("serverResponseLabelError");
						serverResponseLabel.setHTML(SERVER_ERROR);
						clientServerDialogBox.center();
						closeButton.setFocus(true);
					}

					public void onSuccess(String result) {
						clientServerDialogBox.setText("Remote Procedure Call");
						serverResponseLabel.removeStyleName("serverResponseLabelError");
						serverResponseLabel.setHTML(result);
						clientServerDialogBox.center();
						closeButton.setFocus(true);
					}
						});
			}
		}




		class LoginButtonHandler implements ClickHandler 
		{
			public void onClick(ClickEvent event) {	loginRequest();	}

			private void loginRequest() 
			{
				// First, we validate the input.
				errorLabel.setText("");
				final String login = loginField.getText();
				final String password = passwordField.getText();

				// for tests /////////////////////////////////////
				if(login.equals("test")){
					RootPanel.get("divLogin").setVisible(false);
					RootPanel.get("divLobby").setVisible(true);	
					return;
				}
				///////////////////////////////////////////////////

				// Then, we send the input to the server.
				loginButton.setEnabled(false);
				userService.logIn(login, password, 
						new AsyncCallback<String>() 
						{
					String userInput = login;
					public void onFailure(Throwable caught) {
						// Show the RPC error message to the user
						clientServerDialogBox.setText("Failed to Conncected to Server\n");
						textToServerLabel.setText(userInput);
						serverResponseLabel.setText("Server is unresponsive.");
						clientServerDialogBox.center();
						closeButton.setFocus(true);
					}

					public void onSuccess(String result) {
						clientServerDialogBox.setText("Successfully Conncected to Server:\n" + result);
						textToServerLabel.setText(userInput);

						if(!result.startsWith("Error"))
						{
							secretUserId.setText(result);
							result = "Successful!";		// We don't want to disclose any UUID
							closeButton.setFocus(true);
							closeButton.addClickHandler(new ClickHandler(){
								@Override
								public void onClick(ClickEvent event) {
									RootPanel.get("divLogin").setVisible(false);
									RootPanel.get("divLobby").setVisible(true);				
								}
							});
						}
						serverResponseLabel.setText(result);
						clientServerDialogBox.center();
					}
						});
			}
		}

		// Add a handler to send the name to the server
		loginButton.addClickHandler(new LoginButtonHandler());
		class SignUpButtonHandler implements ClickHandler 
		{
			@Override
			public void onClick(ClickEvent event) {
				RootPanel.get("divLogin").setVisible(false);
				RootPanel.get("divRegistration").setVisible(true);				
			}
		}
		signUpButton.addClickHandler(new SignUpButtonHandler());

		class CancelButtonHandler implements ClickHandler 
		{
			@Override
			public void onClick(ClickEvent event) {
				RootPanel.get("divLogin").setVisible(true);
				RootPanel.get("divRegistration").setVisible(false);				
			}
		}
		cancelButton.addClickHandler(new CancelButtonHandler());

		class RegisterButtonHandler implements ClickHandler 
		{
			public void onClick(ClickEvent event) {	registerRequest();	}

			private void registerRequest() 
			{
				// First, we validate the input.
				errorLabel.setText("");
				final String firstName = fisrtNameField.getText();
				final String lastName = lastNameField.getText();
				final String login = newLoginField.getText();
				final String password = newPasswordField.getText();

				// Then, we send the input to the server.
				loginButton.setEnabled(false);

				userService.register(firstName, lastName, login, password, 
						new AsyncCallback<String>() 
						{
					String userInput = firstName + " " + lastName + " " + login + "\n\r"  + password;
					public void onFailure(Throwable caught) {
						// Show the RPC error message to the user
						clientServerDialogBox.setText("Failed to Conncected to Server\n");
						textToServerLabel.setText(userInput);
						serverResponseLabel.setText("Server is unresponsive.");
						clientServerDialogBox.center();
						closeButton.setFocus(true);
					}

					public void onSuccess(String result) {
						clientServerDialogBox.setText("Successfully Conncected to Server:\n" + result);
						textToServerLabel.setText(userInput);
						serverResponseLabel.setText(result);
						clientServerDialogBox.center();
						closeButton.setFocus(true);
						RootPanel.get("divLogin").setVisible(true);
						RootPanel.get("divRegistration").setVisible(false);	
						loginField.setText(login);
						passwordField.setText(password);
					}
						});
			}
		}
		registerButton.addClickHandler(new RegisterButtonHandler());
	}



}
